/*----------------------------------------------------------------------------------------
*
*  Copyright 2019, Gao Hai Hui, <fromzeropoint@126.com>.  All rights reserved.
*  https://gitee.com/helloworldghh/xoskit.git
*  Use of this source code is governed by a MIT license
*  that can be found in the License file.
*
----------------------------------------------------------------------------------------*/
#include "../import/head.h"
#include "../data_struct/head.h"
#include "../macro/head.h"
#include "odbc_connect_pool.h"
#include "odbc_connect.h"
#include "hook.h"
#include "mgr.h"

namespace xos_odbc
{

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    static xos_container::i_container* container_ptr = 0;
    static mgr* mgr_ptr = 0;

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    mgr::mgr()
    {
        init_data();
    }

    mgr::~mgr()
    {
    }

    //////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::static_init( xos_container::i_container* pContainer, i_odbc_mgr** ppv )
    {
        return xos_stl::static_init_module( pContainer, ppv, container_ptr, mgr_ptr );
    }

    xos_container::i_container* mgr::container()
    {
        return container_ptr;
    }

    mgr* mgr::get()
    {
        return mgr_ptr;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::connect( void * hWnd, const char * lpszConnectStr, i_connect ** ppDbc )
    {
        int ret = 0;

        i_connect * pDbc = 0;

        if( 0 == ret )
        {
            ret = create_connect( hWnd, lpszConnectStr, &pDbc );
        }

        if( 0 == ret )
        {
            ret = pDbc->connect();
        }

        if( ( 0 == ret ) && ppDbc )
        {
            *ppDbc = pDbc;
            pDbc = 0;
        }

        xos_stl::release_interface( pDbc );

        return ret;
    }

    i_connect_pool * mgr::connect_pool( const char * lpszConnectStr )
    {
        odbc_connect_pool::T * pRet = 0;
        xos_stl::init_pool_item( pRet );
        pRet->set_connect_str( lpszConnectStr );
        return pRet;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::put_back_to_pool()
    {
        int ret = 0;
        delete this;
        return ret;
    }

    int mgr::init()
    {
        int ret = 0;

        if( 0 == ret )
        {
            ret = init_env();
        }

        if( 0 == ret )
        {
            ret = hook::init();
        }

        return ret;
    }

    int mgr::term()
    {
        int ret = 0;
        term_env();
        init_data();
        hook::term();
        return ret;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 

    int mgr::create_connect( void * hWnd, const char * lpszConnectStr, i_connect ** ppDbc )
    {
        int ret = 0;

        SQLHANDLE hDbc = SQL_NULL_HDBC;

        if( ( 0 == ret ) && ( SQL_NULL_HANDLE == m_hEnv ) )
        {
            ret = 1;
        }

        if( 0 == ret )
        {
            SQLRETURN r = SQLAllocHandle( SQL_HANDLE_DBC, m_hEnv, &hDbc );
            ret = m_err.connect_ret( hDbc, r );
        }

        if( ( 0 == ret ) && ppDbc )
        {
            odbc_connect::T * pT = 0;
            xos_stl::init_pool_item( pT );
            pT->set_connect_info( hWnd, lpszConnectStr );
            pT->set_handle( hDbc );
            *ppDbc = pT;
            hDbc = SQL_NULL_HDBC;
        }

        if( SQL_NULL_HDBC != hDbc )
        {
            SQLDisconnect( hDbc );
            SQLFreeHandle( SQL_HANDLE_DBC, hDbc );
            hDbc = SQL_NULL_HDBC;
        }

        return ret;
    }

    int mgr::init_data()
    {
        int ret = 0;
        m_hEnv = SQL_NULL_HANDLE;
        m_err.clear();
        return ret;
    }

    int mgr::init_env()
    {
        int ret = 0;

        if( 0 == ret )
        {
            SQLRETURN r = SQLAllocHandle( SQL_HANDLE_ENV, SQL_NULL_HANDLE, &m_hEnv );
            ret = m_err.env_ret( m_hEnv, r );
        }

        if( 0 == ret )
        {
            SQLRETURN r = SQLSetEnvAttr( m_hEnv, SQL_ATTR_ODBC_VERSION, ( SQLPOINTER )SQL_OV_ODBC3, 0 );
            ret = m_err.env_ret( m_hEnv, r );
        }

        return ret;
    }

    int mgr::term_env()
    {
        int ret = 0;

        if( SQL_NULL_HANDLE != m_hEnv )
        {
            SQLFreeHandle( SQL_HANDLE_ENV, m_hEnv );
            m_hEnv = SQL_NULL_HANDLE;
        }

        return ret;
    }

} // xos_odbc
